// =============================================================================
//  Spangles Analyzer
//
//  Copyright(c) 2008
//  See LICENSE.txt for licensing information.
// =============================================================================

package com.google.spangles.domain;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import com.google.spangles.interfaces.impl.CollectionBounded;
import com.google.spangles.interfaces.impl.CompositeBounded;

/**
 * (Description)
 * (Any invariants [conditions that are always true] )
 * (Usage instructions, and/or examples)
 * (TODOs, ASSUMPTIONs, etc.)
 * (Known Bugs)
 * (Concurrency strategy - not thread safe or how it's thread safe)
 * 
 * @author Chris
 */
public class GameState
{
   Position position;
   
   private GameState(Color color, Map<Location, Color> layout)
   {
      this(new Position(color, layout));
   }
   
   private GameState(Position pos)
   {
      this.position = pos;
   }
   
   public static GameState createEmpty()
   {
      Map<Location, Color> layout = new HashMap<Location, Color>();
      return new GameState(Color.WHITE, layout);
   }
   
   public static GameState createNew()
   {
      Map<Location, Color> layout = new HashMap<Location, Color>();
      layout.put(new Location(0,0), Color.BLACK);
      layout.put(new Location(0,1), Color.WHITE);      
      return new GameState(Color.WHITE, layout);
   }

   /**
    * (Description - what the method does and why)
    * (Visibility decision, if not obvious)
    * (Pre/Post Conditions)
    * (Usage examples)
    * (Algorithmic notes)
    * (Concurrency issues)
    * @return
    */
   public Map<Location, Color> getLayout()
   {
      return position.getLayout();
   }

   /**
    * (Description - what the method does and why)
    * (Visibility decision, if not obvious)
    * (Pre/Post Conditions)
    * (Usage examples)
    * (Algorithmic notes)
    * (Concurrency issues)
    * @return
    */
   public Collection<Location> getValidMoves()
   {
      return position.getValidMoves();
   }

   /**
    * (Description - what the method does and why)
    * (Visibility decision, if not obvious)
    * (Pre/Post Conditions)
    * (Usage examples)
    * (Algorithmic notes)
    * (Concurrency issues)
    * @param i
    * @param j
    */
   public Color playRelative(int column, int row)
   {
      Set<Location> validMoves = position.getValidMoves();
      
      CompositeBounded cb = new CompositeBounded();
      cb.addBounded(position);
      cb.addBounded(new CollectionBounded(validMoves));
      
      int xo = cb.getMinimumX();
      int yo = cb.getMinimumY();
      
      Location l = new Location(xo+column, yo+row);
      
      if(!validMoves.contains(l))
      {
         throw new UnsupportedOperationException("Cannot play at position " + l + " (offset "+column + "," + row);
      }
      position = position.playPiece(l);
      return position.checkWin(l);
   }

   /**
    * (Description - what the method does and why)
    * (Visibility decision, if not obvious)
    * (Pre/Post Conditions)
    * (Usage examples)
    * (Algorithmic notes)
    * (Concurrency issues)
    * @return
    */
   public GameState deadTileElimination()
   {
      Position dte = position.deadTileElimination();
      return new GameState(dte);
   }

}
